#_*_ coding:UTF-8 _*_
import  math
import os
import copy
from DataCleaning import DataCleaning
from ConnectTrack import ConnectTrack
from  StopAndLook import StopAndlook
import time
from  ToMysql import  ToMysql
import numpy as np
# from dtw import dtw
from  fastdtw import fastdtw
# from  fastdtw import dtw

class SimilarTrack:
    '''
    判断顾客和销售的轨迹是否相似以及顾客是否上车
    '''
    def __init__(self):
        pass

    def inCar(self,startAndEnd,bordTime,threshold,distance,allIdMap,trueIdMap,trackspath,cameras):
        '''
        在空间坐标系中判断顾客是否上车（在多个摄像头下只要有一个摄像头判断该顾客上车了，
        则该顾客就上车了）
        :param startAndEnd: {摄像头id：{车id：{顾客id：list（顾客坐标）}}}存储可能看车的顾客的轨迹
        :param bordTime:顾客上车时间的阈值（str）
        :param threshold:用户上车时离车的距离（str）
        :param distance:拼接两条轨迹时需要度量的距离的阈值（str）
        :param allIdMap:存储各个摄像头下的ID之间的映射关系，直接从原始文件中读取（dict）
        :param trueIdMap:（dict）存储各个摄像头下的ID之间的映射关系，通过拼接得到的
        :param trackspath:(dict)每所有摄像头对应的顾客轨迹的dataframe{摄像头id：dataFrame}
        :param cameras:(dict)不同摄像头下的车辆位置
        :return:{车id：上车的顾客（list）}
        '''
        dc=DataCleaning(startAndEnd)
        startAndEnd1=copy.deepcopy(startAndEnd)
        borad={}  #camerid:{carid:consumer(list)}
        for camerakey in startAndEnd1:#每个摄像头
            consumers={}
            temp=startAndEnd1[camerakey]
            for carkey in  temp:#每辆车
               incarconsumer=[]
               tempcon=temp[carkey]
               carCoord=cameras[camerakey][carkey].split(",")
               carCoord[-1]=str(float(carCoord[-1])/2.0)
               isCompute=[]
               for consumerkey in tempcon:#每个顾客
                   # 比较前后两个轨迹点的帧数差以及离车的距离是否满足上车的要求
                    if consumerkey in isCompute:
                        continue
                    tag=False
                    consumer=tempcon[consumerkey]#记录已经计算过的顾客ID

                   #两两比较顾客看车的前后两个轨迹点，看是否有上车行为
                    startStr=consumer[0].split(",")
                    if len(startStr)==7:
                        # s=startStr[0]
                        # e=startStr[0]
                        # x1=startStr[2]
                        # x2=startStr[2]
                        # y1=startStr[3]
                        # y2=startStr[3]
                        # width1=startStr[4]
                        # width2=startStr[4]
                        # sration=startStr[6]
                        # eration=startStr[6]
                        s,e,x1,x2,y1,y2,width1,width2,height1,height2,sration,eration=[startStr[0],startStr[0],startStr[2],startStr[2], \
                                                startStr[3],startStr[3],startStr[4],startStr[4],startStr[5],startStr[5],startStr[6],startStr[6]]
                    else:
                        print "数据有残缺--inCar"
                    for i in xrange(1,len(consumer)):
                        mindStr=consumer[i].split(",")
                        if len(mindStr)==7:
                            # e=mindStr[0]
                            # eration=mindStr[6]
                            # x2=mindStr[2]
                            # y2=mindStr[3]
                            # width2=mindStr[4]
                            e,eration,x2,y2,width2,height2=[mindStr[0],mindStr[6],mindStr[2],mindStr[3],mindStr[4],mindStr[5]]
                        else:
                            print "数据有残缺--inCar"
                        #前后两个轨迹点是否满足上车的条件，有跳帧，且离车较近
                        if float(e)-float(s)>=float(bordTime) and float(e)-float(s)<=(float(bordTime)*15.0) and  float(sration)>=float(threshold) and  float(eration) >=float(threshold):
                            inCarRation1=dc.overlopArea(carCoord,[x1,y1,width1,height1])
                            inCarRation2=dc.overlopArea(carCoord,[x2,y2,width2,height2])
                            if inCarRation1>=0.1 and inCarRation2>=0.1:#and还是or
                                isCompute.append(consumerkey)
                                tag=True
                                break
                        else:
                            # s=e
                            # sration=eration
                            # x1=x2
                            # y1=y2
                            # width1=width2
                            s,sration,x1,y1,width1,height1=[e,eration,x2,y2,width2,height2]

                    #针对顾客上车后下车轨迹发生变化的情况，对轨迹做拼接
                    if not tag and  float(sration)>=float(threshold):
                        for anotherconsumerkey in tempcon:#遍历车辆周围的所有轨迹点，根据轨迹的拼接情况判断顾客是否上车
                            if anotherconsumerkey != consumerkey and anotherconsumerkey not in isCompute:
                                anotherconsumer=tempcon[anotherconsumerkey]
                                firstNode=anotherconsumer[0].split(",")
                                if float(firstNode[6])>=float(threshold) and float(firstNode[0])-float(s)>=float(bordTime) and  float(firstNode[0])-float(s)<=(float(bordTime)*15.0) and\
                                                        self.euclideanDistances(x1,y1,firstNode[2],firstNode[3])/float(width1)<=float(distance) :
                                    inCarRation = dc.overlopArea(carCoord, [x1, y1, width1, height1])
                                    if inCarRation >= 0.1:
                                        isCompute.append(anotherconsumerkey)
                                        tag=True
                                        break

                    if tag:
                        incarconsumer.append(consumerkey)

               if incarconsumer:
                    consumers[carkey]=incarconsumer
                     #print  incarconsumer

            if consumers:
                borad[camerakey]=consumers
                #print consumers

        # 先进行顾客id的关联
        ct = ConnectTrack(trackspath, allIdMap)
        boradMap={}
        for camerakey in borad:
            data=trackspath[camerakey]
            data=data[data.is_customer==1]
            idMap=allIdMap[camerakey]#单摄像头下原始的顾客ID映射，（直接从原始文件中读出）
            if trueIdMap.has_key(camerakey):
                aloneTrueIdMap=trueIdMap[camerakey]#单摄像头下顾客ID映射，（通过拼接得到）
            else:
                aloneTrueIdMap ={}
            # realId=allRealId[camerakey]
            ct.setIdMap(idMap)
            ct.setTrackFile(data)
            tempBorad=borad[camerakey]
            carBoard={}
            for carkey in tempBorad:
                conList=tempBorad[carkey]
                con=[]
                for consumer in conList:
                    if idMap[consumer] !="":#原始文件中有映射关系
                        con.append(idMap[consumer])
                    else:#原始文件中没有映射关系
                        if aloneTrueIdMap.has_key(consumer):#已经拼接成功过
                            con.append(aloneTrueIdMap[consumer])
                        else:#还我没有拼接过
                            trueID=ct.connect(consumer)
                            if idMap[trueID[-1]]!="":
                                con.append(idMap[trueID[-1]])
                carBoard[carkey]=con
            boradMap[camerakey]=carBoard

        #统计上车人数(多个摄像头合在一起,有一个摄像头判断该用户上车了，则该用户上车)
        #如果是多个摄像头关联的话，应该是先关联，最后合并
        cars=[]
        for  camerakey in boradMap:
            tempdict=boradMap[camerakey]
            for carkey in tempdict:
                if carkey not in cars:
                    cars.append(carkey)

        allInCar={}
        for i in  cars:
            allconsumers=[]
            for camerakey in boradMap:#把多个摄像头下的上车顾客合并到一起
                templist1=boradMap[camerakey]
                if i in templist1.keys():
                    templist=templist1[i]
                    for con in templist:
                        if con not  in allconsumers:
                            allconsumers.append(con)

            allInCar[i]=allconsumers

        return  allInCar#已经映射过的上车用户


    def inCarTempId(self,startAndEnd,bordTime,threshold,distance,cameras):
        '''
        在空间坐标系中判断顾客是否上车（在多个摄像头下只要有一个摄像头判断该顾客上车了，
        则该顾客就上车了）
        :param startAndEnd: {摄像头id：{车id：{顾客id：list（顾客坐标）}}}存储可能看车的顾客的轨迹
        :param bordTime:顾客上车时间的阈值（str）
        :param threshold:用户上车时离车的距离（str）
        :param distance:拼接两条轨迹时需要度量的距离的阈值（str）
        :param cameras:(dict)各个摄像头下车辆的坐标位置
        :return:{车id：上车的顾客（list）}
        '''
        dc=DataCleaning(startAndEnd)
        boardTime={}#统计上车时间
        startAndEnd1=copy.deepcopy(startAndEnd)#复制数据，防止在程序执行的过程中改变原始数据
        borad={}  #camerid:{carid:consumer(list)}
        for camerakey in startAndEnd1:#每个摄像头
            consumers={}
            temp=startAndEnd1[camerakey]
            time={}
            for carkey in  temp:#每辆车
               incarconsumer=[]
               tempcon=temp[carkey]
               carCoord = cameras[camerakey][carkey].split(",")#当前摄像头下车辆的位置
               carCoord[-1] = str(float(carCoord[-1]) / 2.0)
               isCompute=[]
               for consumerkey in tempcon:#每个顾客
                   # 比较前后两个轨迹点的帧数差以及离车的距离是否满足上车的要求
                    tag=False
                    consumer=tempcon[consumerkey]#记录已经计算过的顾客ID
                    if consumerkey in isCompute:
                        continue
                   #两两比较顾客看车的前后两个轨迹点，看是否有上车行为
                    startStr=consumer[0].split(",")
                    if len(startStr)==7:
                        s,e,x1,x2,y1,y2,width1,width2,height1,height2,sration,eration=map(float,[startStr[0],startStr[0],startStr[2],startStr[2],\
                                                    startStr[3],startStr[3],startStr[4],startStr[4],startStr[5],startStr[5],startStr[6],startStr[6]])
                        # s=startStr[0]
                        # e=startStr[0]
                        # x1=startStr[2]
                        # x2=startStr[2]
                        # y1=startStr[3]
                        # y2=startStr[3]
                        # width1=startStr[4]
                        # width2=startStr[4]
                        # sration=startStr[6]
                        # eration=startStr[6]
                    else:
                        print "数据有残缺--inCar"
                    for i in xrange(1,len(consumer)):
                        mindStr=consumer[i].split(",")
                        if len(mindStr)==7:
                            e,eration,x2,y2,width2,height2=map(float,[mindStr[0],mindStr[6],mindStr[2],mindStr[3],mindStr[4],mindStr[5]])
                            # e=mindStr[0]
                            # eration=mindStr[6]
                            # x2=mindStr[2]
                            # y2=mindStr[3]
                            # width2=mindStr[4]
                        else:
                            print "数据有残缺--inCar"
                        #前后两个轨迹点是否满足上车的条件，有跳帧，且离车较近
                        if e-s>=float(bordTime) and e-s<=(float(bordTime)*15.0)  and  sration>=float(threshold) and  eration >=float(threshold):
                            inCarRation1 = dc.overlopArea(carCoord, [x1, y1, width1, height1])
                            inCarRation2 = dc.overlopArea(carCoord, [x2, y2, width2, height2])
                            if inCarRation1 >= 0.1 and inCarRation2 >= 0.1:  # and还是or
                                isCompute.append(consumerkey)
                                tag=True
                                if time.has_key(carkey):#上车帧数
                                    time[carkey]=time[carkey]+(e-s)/250.0
                                else:
                                    time[carkey] = (e-s)/250.0
                                break
                        else:
                            s,sration,x1,y1,width1,height1=[e,eration,x2,y2,width2,height2]
                            # s=e
                            # sration=eration
                            # x1=x2
                            # y1=y2
                            # width1=width2

                    #针对顾客上车后下车轨迹发生变化的情况，对轨迹做拼接
                    if not tag and  sration>=threshold:
                        for anotherconsumerkey in tempcon:#遍历车辆周围的所有轨迹点，根据轨迹的拼接情况判断顾客是否上车
                            if anotherconsumerkey != consumerkey and anotherconsumerkey not in isCompute:
                                anotherconsumer=tempcon[anotherconsumerkey]
                                firstNode=anotherconsumer[0].split(",")
                                if float(firstNode[6])>=float(threshold)  and float(firstNode[0])-float(s)>=float(bordTime) and float(firstNode[0])-float(s)<=(float(bordTime)*30.0) and\
                                        self.euclideanDistances(x1,y1,firstNode[2],firstNode[3])/float(width1)<=float(distance) :#上车时间大于20s小于10min
                                    inCarRation = dc.overlopArea(carCoord, [x1, y1, width1, height1])
                                    if inCarRation >= 0.1:
                                        isCompute.append(anotherconsumerkey)
                                        if time.has_key(carkey):#看车时间
                                            time[carkey] = time[carkey] + (float(firstNode[0])-float(s))/250
                                        else:
                                            time[carkey] = (float(firstNode[0])-float(s))/250
                                        tag=True
                                        break

                    if tag:
                        incarconsumer.append(consumerkey)

               if incarconsumer:
                    consumers[carkey]=incarconsumer
                     #print  incarconsumer
            boardTime[camerakey]=time
            if consumers:
                borad[camerakey]=consumers
                #print consumers


        #统计上车人数
        boradNums={}#上车次数
        cars=[]
        for  camerakey in borad:#统计总共有多少量车
            tempdict=borad[camerakey]
            for carkey in tempdict:
                if carkey not in cars:
                    cars.append(carkey)

        #统计上车人数和时间
        for i in  cars:
            allconsumers=[]
            for camerakey in borad:#把多个摄像头下的上车顾客合并到一起
                templist1=borad[camerakey]
                if i in templist1.keys():
                    templist=templist1[i]
                    if boradNums.has_key(i):
                        boradNums[i]=boradNums[i]+len(templist)
                    else:
                        boradNums[i] = len(templist)#上车人数
        allBoardNum={}
        for i in cars:
            allconsumers = []
            for camerakey in boardTime:  # 把多个摄像头下的上车顾客合并到一起
                templist1 = boardTime[camerakey]
                if i in templist1.keys():
                    templist = templist1[i]
                    if allBoardNum.has_key(i):#上车时间
                        allBoardNum[i] = allBoardNum[i] + int(templist)
                    else:
                        allBoardNum[i] = int(templist)

        # for carkey in allBoardNum:
        #     allBoardNum[carkey]=allBoardNum[carkey]/250
        return  borad,boradNums,allBoardNum#不同摄像头下的看车顾客，看车次数，看车时间

    def euclideanDistances(self,x1,y1,x2,y2):
        '''
        计算两点之间的欧式距离
        :param x1: （str）横坐标
        :param y1: （str）纵坐标
        :param x2: （str）横坐标
        :param y2: （str）纵坐标
        :return: （float）两点之间的欧式距离
        '''
        return math.sqrt(math.pow(float(x1)-float(x2),2)+math.pow(float(y1)-float(y2),2))


    #jython DTW算法
    def  computeGridMatrix(self,track1,track2):
        '''
        计算两条轨迹的网格矩阵(dtw算法的第一步）
        :param track1: （list）轨迹1
        :param track2:（list）轨迹2
        :return: （list）网格矩阵
        '''
        gridMatrix=[]
        for i in xrange(len(track1)):
            tmp=[]
            for j in xrange(len(track2)):
                tmp.append(self.euclideanDistances(track1[i][0],track1[i][1],track2[j][0],track2[j][1]))
            gridMatrix.append(tmp)
        return gridMatrix

    # jython DTW算法
    def computSimilarity(self,gridMatrix):
        '''
        通过网格矩阵计算两条轨迹的相似度
        :param gridMatrix:（list）两条轨迹的网格矩阵
        :return:（float）两条轨迹之间的距离
        '''

        #初始化距离矩阵
        warping=[]
        x=len(gridMatrix)
        y=len(gridMatrix[-1])
        for i in xrange(x):
            tmp=[]
            for j in xrange(y):
                tmp.append(0)
            warping.append(tmp)

        for i in xrange(x):
            for j in xrange(y):
                if i==0 and j==0:
                    warping[i][j]=float(gridMatrix[i][j])
                elif i==0 and j!=0:
                    warping[i][j]=float(gridMatrix[i][j])+float(warping[i][j-1])
                elif i!=0 and j==0:
                    warping[i][j]=float(gridMatrix[i][j])+float(warping[i-1][j])
                elif i!=0 and j!=0:
                    warping[i][j]=float(gridMatrix[i][j])+min(min(float(warping[i-1][j]),float(warping[i][j-1])),float(warping[i-1][j-1]))

        # print warping
        return warping[x-1][y-1]




    def saleFollow(self,consumerX,saleY):
        '''
        计算销售和顾客轨迹之间的距离
        :param x:（list）顾客的轨迹数据，例如[[0, 0], [1, 1], [2, 4], [2, 1], [2, 0],[3,3]]
        :param y:（list）销售的轨迹数据，例如[[1, 1], [1, 2], [2, 2], [2, 3], [2, 0],[10,3],[3,4],[5,4]]
        :return: distance(float)
        '''
        # jython DTW算法
        # gridMatrix=self.computeGridMatrix(consumerX,saleY)
        # distance=self.computSimilarity(gridMatrix)
        # return distance

        if len(saleY)/float(len(consumerX))<0.5:
            return "1000000.0"

        x=np.array(consumerX).reshape(-1,2)
        y=np.array(saleY).reshape(-1,2)
        dist,path= fastdtw(x, y, dist = lambda x, y: math.sqrt(math.pow(float(x[0]) - float(y[0]), 2) + math.pow(float(x[1]) - float(y[1]), 2)))
        return  dist

    def togetherGo(self,consumerX,saleY):
        '''
        计算销售和顾客轨迹之间的距离
        :param x:（list）顾客的轨迹数据，例如[[0, 0], [1, 1], [2, 4], [2, 1], [2, 0],[3,3]]
        :param y:（list）销售的轨迹数据，例如[[1, 1], [1, 2], [2, 2], [2, 3], [2, 0],[10,3],[3,4],[5,4]]
        :return: distance(float)
        '''
        # jython DTW算法
        # gridMatrix=self.computeGridMatrix(consumerX,saleY)
        # distance=self.computSimilarity(gridMatrix)
        # return distance

        # if len(saleY)/float(len(consumerX))<0.5:
        #     return "1000000.0"

        x=np.array(consumerX).reshape(-1,2)
        y=np.array(saleY).reshape(-1,2)
        dist,path = fastdtw(x, y, dist = lambda x, y: math.sqrt(math.pow(float(x[0]) - float(y[0]), 2) + math.pow(float(x[1]) - float(y[1]), 2)))
        return  dist

    def isFollowInDoor(self,dataInDoor,startFrame,endFrame,threshold,idMAp):
        '''
        判断顾客进门后销售有没有跟随
        :param dataInDoor:（DataFrame)存放门口摄像头轨迹的DataFrame
        :param startFrame:（int）轨迹的绝对起始帧数
        :param endFrame:(int）轨迹的绝对结束帧数
        :param threshold:(float)判断顾客是否被跟随的阈值
        :param idMAp:(dict)门口摄像头下trueID和tempID之间的映射关系
        :return:dict {顾客：“销售，顾客和销售之间的距离”}
        '''
        follows = {}
        dataConsumer=dataInDoor[dataInDoor.is_customer==1]#顾客轨迹
        dataSale=dataInDoor[dataInDoor.is_customer==2]#销售轨迹

        for dirs in idMAp:
            if  idMAp[dirs]=="":#没有真实ID的顾客不计算
                continue
            group=dataConsumer[dataConsumer.tmp_id==float(dirs)]
            conStart=group.frame.values[0]
            if len(group.values)<16:#如果顾客的轨迹点过少，则不判断
                continue
            conStart = float(conStart) + startFrame
            conEnd = conStart + float(endFrame)*250
            # if conEnd-conStart<=20:
            #     continue
            conTrack = DataCleaning(dataConsumer).subTrack(group, conStart, conEnd)  # 获取顾客轨迹
            consumerID = idMAp[dirs]
            for j, group1 in dataSale.groupby('tmp_id'):#遍历每一个销售，看是否跟随了该顾客
                j=str(j)
                s=group1.values[0][0]
                if float(s)>(conStart+conEnd)/2:
                    continue
                saleTrack = DataCleaning(dataSale).subTrack(group1, conStart, conEnd)
                t1, t2 = self.getTrackMat(conTrack, saleTrack)
                value = self.saleFollow(t1, t2)
                if value <= threshold:
                    if str(j) != consumerID:  # 测试时没有数据，所以，加了这样的条件，真实数据中不需要这样的条件
                        follows[consumerID] = str(j) + "," + str(value)
                        # print consumerID+","+tempId+","+str(value)
                        break

            # print "相似轨迹判断时间-end" + str(time.time())
            # print "-----------------------------------------"
        return follows  # 客户真实ID：销售临时ID

    def isFollowInDoorTmpID(self,dataInDoor,startFrame,endFrame,threshold,idMAp):
        '''
        判断顾客进门后销售有没有跟随(用临时ID做)
        :param dataInDoor:（DataFrame)存放门口摄像头轨迹的DataFrame
        :param startFrame:（int）轨迹的绝对起始帧数
        :param endFrame:(int）轨迹的绝对结束帧数
        :param threshold:(float)判断顾客是否被跟随的阈值
        :param idMAp:(dict)门口摄像头下trueID和tempID之间的映射关系
        :return:dict {顾客：“销售，顾客和销售之间的距离”}
        '''
        follows = {}
        dataConsumer=dataInDoor.loc[lambda df: df.is_customer==1]#顾客轨迹
        dataSale=dataInDoor.loc[lambda df: df.is_customer==2]#销售轨迹

        for dirs in idMAp:
            # if  idMAp[dirs]=="":#没有真实ID的顾客不计算
            #     continue
            # 对所有的临时ID计算
            group=dataConsumer.loc[lambda  df : df.tmp_id==float(dirs)]
            # conStart=group.frame.values[0]#取第一帧
            conEnd = group.frame.values[-1]  # 取最后一帧
            if len(group.values)<16:#如果顾客的轨迹点过少，则不判断
                continue

            # conStart = float(conStart) + startFrame#先取第一帧，然后算出最后一帧
            # conEnd = conStart + float(endFrame)*250
            conStart = float(conEnd) -float(endFrame)*250#先取最后一帧，然后算出第一帧

            # if conEnd-conStart<=20:
            #     continue
            conTrack = DataCleaning(dataConsumer).subTrack(group, conStart, conEnd)  # 获取顾客轨迹
            consumerID = dirs
            for j, group1 in dataSale.groupby('tmp_id'):#遍历每一个销售，看是否跟随了该顾客
                j=str(j)
                s = group1.values[0][0]
                if float(s) > (conStart + conEnd)/2  or abs(float(j)-float(dirs))>=100.0:#如果销售出现的时间段和顾客的轨迹不匹配，则直接跳过
                    continue
                saleTrack = DataCleaning(dataSale).subTrack(group1, conStart, conEnd)
                t1, t2 = self.getTrackMat(conTrack, saleTrack)
                value = self.saleFollow(t1, t2)
                if value <= threshold:

                    if str(j) != consumerID:  # 测试时没有数据，所以，加了这样的条件，真实数据中不需要这样的条件
                        follows[consumerID] = str(j) + "," + str(value)
                        # print consumerID+","+tempId+","+str(value)
                        break

            # print "相似轨迹判断时间-end" + str(time.time())
            # print "-----------------------------------------"
        return follows  # 客户真实ID：销售临时ID


    def  isFollowInCar(self,startAndEnd,allData,lenOfTrack,isFollow,followsInDoor,allIdMap):
        '''
        判断顾客看车时是否有销售跟随
        :param startAndEnd:(dict){摄像头id：{车辆id：{顾客id：坐标（list）}}}，不同摄像头下载车辆周围有停留的顾客数据
        :param allData:(dict){摄像头ID:DataFrame}
        :param lenOfTrack:(int)判断顾客是否被跟随的轨迹长度
        :param isFollow:(float)判断顾客是否被销售跟随的阈值
        :param followsInDoor:(dict)在门口被销售跟随的顾客（顾客的ID必须是真实ID）
        :param allIdMap:(dict)多个摄像头下顾客临时ID和真实ID之间的映射
        :return:(dict){摄像头ID:{顾客：“销售，顾客和销售之间的距离”}}
        '''
        ct = ConnectTrack(allData, allIdMap)
        follows={}
        trueIdMap={}
        dc=DataCleaning(allData)
        startAndEnd1=copy.deepcopy(startAndEnd)#深度拷贝，防止在程序执行的过程中变更StartAndEnd的值
        for camerakey in startAndEnd1:
            # print camerakey
            aloneSaleFile=allData[camerakey]#单摄像头下的销售轨迹
            aloneSaleFile=aloneSaleFile[aloneSaleFile.is_customer==2]
            aloneTracksPath=allData[camerakey]#单摄像头下的顾客轨迹
            aloneTracksPath=aloneTracksPath[aloneTracksPath.is_customer==1]
            idMap=allIdMap[camerakey]#单摄像头下的id映射关系
            ct.setTrackFile(aloneTracksPath)#轨迹拼接数据设置
            ct.setIdMap(idMap)


            aloneSAE=startAndEnd1[camerakey]
            aloneFollow={}#单个摄像头下被跟随顾客真实ID和销售id之间的映射关系
            isFollowTmp=[]#被销售跟随的顾客的临时id列表
            someTrueIdMap={}#单个摄像头下临时ID和拼接到的真实ID之间的映射

            for  carkey in aloneSAE:
                con=aloneSAE[carkey]
                for consumerkey in con:
                    if consumerkey in isFollowTmp:#在同一个摄像头下，顾客在看某一辆车是已经有销售跟随，则不会重复判断
                        continue
                    if idMap[consumerkey]=="":#没有trueID
                        connectID = ct.connect(consumerkey)[-1]
                        if idMap[connectID]!="":#拼接成功
                            someTrueIdMap[consumerkey]=idMap[connectID]
                            if followsInDoor.has_key(someTrueIdMap[consumerkey]):
                                continue
                        else:#拼接失败
                            continue
                    if followsInDoor.has_key(idMap[consumerkey]):#有trueID，如果该顾客在进门时已经有销售跟随，则在这里不重复判断
                        continue

                    eFrame=con[consumerkey][0].split(",")[0]
                    sFrame=float(eFrame)-lenOfTrack*0#起始看车帧数
                    eFrame=float(eFrame)+lenOfTrack*2*250#结束帧数
                    # if sFrame<=0:
                    #     sFrame=1

                    consumerPath=aloneTracksPath[aloneTracksPath.tmp_id==float(consumerkey)]#顾客的轨迹数据
                    conTrack=dc.subTrack(consumerPath,sFrame,eFrame)
                    if len(conTrack)<20:
                        continue
                    for i, group in aloneSaleFile.groupby('tmp_id'):#遍历每个销售
                        i=str(i)
                        s = group.values[0][0]
                        if float(s) > (sFrame + eFrame) / 2:
                            continue
                        saleTrack = dc.subTrack(group, sFrame, eFrame)
                        t1, t2 = self.getTrackMat(conTrack, saleTrack)
                        value = self.saleFollow(t1, t2)#销售跟随顾客的值
                        if float(value) <= isFollow:
                            saleId = i  # 销售ID
                            isFollowTmp.append(consumerkey)
                            if saleId != consumerkey:  # 测试时没有数据，所以，加了这样的条件，真实数据中不需要这样的条件
                                if idMap[consumerkey] != "":
                                    aloneFollow[idMap[consumerkey]] = saleId + "," + str(value)  # 真实ID
                                else:
                                    aloneFollow[someTrueIdMap[consumerkey]] = saleId + "," + str(value)
                                # print consumerkey + "," + saleId+ "," + str(value)
                                break

                    follows[camerakey] = aloneFollow
                    trueIdMap[camerakey] = someTrueIdMap

        return follows,trueIdMap

    def isFollowInCarTmpId(self, startAndEnd, allData, lenOfTrack, isFollow):
        '''
        判断顾客看车时是否有销售跟随(临时ID)
        :param startAndEnd:(dict){摄像头id：{车辆id：{顾客id：坐标（list）}}}，不同摄像头下载车辆周围有停留的顾客数据
        :param allData:(dict){摄像头ID:DataFrame}
        :param lenOfTrack:(int)判断顾客是否被跟随的轨迹长度
        :param isFollow:(float)判断顾客是否被销售跟随的阈值
        :return:(dict){摄像头ID:{顾客：“销售，顾客和销售之间的距离”}}
        '''
        # ct = ConnectTrack(allData, allIdMap)
        follows = {}
        # trueIdMap = {}
        dc = DataCleaning(allData)
        startAndEnd1 = copy.deepcopy(startAndEnd)  # 深度拷贝，防止在程序执行的过程中变更StartAndEnd的值
        for camerakey in startAndEnd1:
            # print camerakey
            aloneSaleFile = allData[camerakey]  # 单摄像头下的销售轨迹
            aloneSaleFile = aloneSaleFile.loc[lambda df : df.is_customer == 2]
            aloneTracksPath = allData[camerakey]  # 单摄像头下的顾客轨迹
            aloneTracksPath = aloneTracksPath.loc[lambda df : df.is_customer == 1]
            # idMap = allIdMap[camerakey]  # 单摄像头下的id映射关系
            # ct.setTrackFile(aloneTracksPath)  # 轨迹拼接数据设置
            # ct.setIdMap(idMap)

            aloneSAE = startAndEnd1[camerakey]
            aloneFollow = {}  # 单个摄像头下被跟随顾客真实ID和销售id之间的映射关系
            isFollowTmp = []  # 被销售跟随的顾客的临时id列表
            # someTrueIdMap = {}  # 单个摄像头下临时ID和拼接到的真实ID之间的映射

            for carkey in aloneSAE:
                con = aloneSAE[carkey]
                for consumerkey in con:
                    if consumerkey in isFollowTmp:#在同一个摄像头下，顾客在看某一辆车是已经有销售跟随，则不会重复判断
                        continue
                    eFrame = con[consumerkey][0].split(",")[0]
                    sFrame = float(eFrame) - lenOfTrack * 0  # 起始看车帧数
                    eFrame = float(eFrame) + lenOfTrack * 2 * 250  # 结束帧数(图片每递增一张，帧数递增250)
                    # if sFrame<=0:
                    #     sFrame=1

                    consumerPath = aloneTracksPath.loc[lambda df:df.tmp_id == float(consumerkey)]  # 顾客的轨迹数据
                    conTrack = dc.subTrack(consumerPath, sFrame, eFrame)
                    if len(conTrack) < 20:
                        continue
                    for i, group in aloneSaleFile.groupby('tmp_id'):  # 遍历每个销售
                        i = str(i)
                        s = group.values[0][0]
                        if float(s) > (sFrame + eFrame) / 2 or abs(float(i)-float(consumerkey))>=100.0:
                            continue
                        saleTrack = dc.subTrack(group, sFrame, eFrame)
                        t1, t2 = self.getTrackMat(conTrack, saleTrack)
                        value = self.saleFollow(t1, t2)  # 销售跟随顾客的值
                        if float(value) <= isFollow:
                            saleId = i  # 销售ID
                            isFollowTmp.append(consumerkey)
                            aloneFollow[consumerkey]=saleId + "," + str(value)
                            break

                    follows[camerakey] = aloneFollow
                    # trueIdMap[camerakey] = someTrueIdMap

        return follows

    def mergeFollows(self,followsInDoor,followInCar,cameraDoor):
        '''
        合并门口跟随和看车跟随的数据
        :param followsInDoor:dict {顾客：“销售，顾客和销售之间的距离”}销售在门口跟随顾客的数据
        :param followInCar:(dict){摄像头ID:{顾客：“销售，顾客和销售之间的距离”}}销售在顾客看车时跟随顾客的数据
        :param cameraDoor: (string)门口的摄像头ID
        :return:{顾客：“销售，顾客和销售之间的距离”}整个4s店中销售跟随顾客的情况
        '''
        allFollows=copy.deepcopy(followInCar)
        if allFollows.has_key(cameraDoor):
            allFollows[cameraDoor].extends(followsInDoor)
        else:
            allFollows[cameraDoor]=followsInDoor

        return allFollows


    def mergeAllFollows(self,allFollows):
        '''
        合并各个摄像头下销售跟随的顾客
        :param allFollows:（dict）各个摄像头下的下手=跟随情况
        :return:（dict）顾客：销售
        '''
        follows={}
        for camerakey in allFollows:
            aloneFollows=allFollows[camerakey]
            for consumerkey in aloneFollows:
                if not follows.has_key(consumerkey):
                    follows[consumerkey]=aloneFollows[consumerkey].split(",")[0]
        return  follows

    def mapFollows(self,allFollows,allIdMap,tracksPath):
        '''
        对销售有跟随的顾客进行IP映射
        :param allFollows:{摄像头ID:{顾客：“销售，顾客和销售之间的距离”}}整个4s店中销售跟随顾客的情况
        :param allIPMap:存储各个摄像头下的ID之间的映射关系（dict）
        :param tracksPath:{cameraID:consumerPath}
        :return:{摄像头ID:{顾客：“销售，顾客和销售之间的距离”}}，{cameraID:{tempId:trueId}}
        '''
        someIdMap={}
        ct=ConnectTrack(tracksPath,allIdMap)
        newFollows={}#映射后，整个4s店中销售跟随顾客的情况
        for camerkey in allFollows:
            idMap=allIdMap[camerkey]
            follows=allFollows[camerkey]
            tempFollows={}
            ct.setIdMap(idMap)#设置拼接轨迹时的相关参数
            ct.setTrackFile(tracksPath[camerkey])

            for consumerkey in follows:
                if idMap[consumerkey]!="":#有对应的真实ID
                    tempFollows[idMap[consumerkey]]=follows[consumerkey]
                else:#没有对应的真实ID，则进行轨迹拼接
                    trueId=ct.connect(consumerkey)
                    if idMap[trueId[-1]]!="":
                        someIdMap[consumerkey]=idMap[trueId[-1]]
                        tempFollows[idMap[trueId[-1]]]=follows[consumerkey]
            if len(tempFollows)>0:
                newFollows[camerkey]=tempFollows

        return newFollows,someIdMap
        # #合并
        # pass

    def getFollowRation(self,follows,allIdMap,threshold):
        '''
        得到被跟随的临时ID占临时id的比例
        :param follows:（dict）被销售跟随的顾客（临时ID）
        :param allIdMap:（dict）各个摄像头下临时ID和真实ID之间的映射
        :param threshold:(float)不同摄像头下被跟随顾客的重复率
        :return:(float)被跟随顾客的比例
        '''
        tmpRatio={}
        for camerakey in follows:
            tmpSum=len(allIdMap[camerakey].keys())*0.67#该摄像头下临时ID的总数
            followsSum=len(follows[camerakey].keys())
            tmpRatio[camerakey]=float(followsSum)/float(tmpSum)

        ratio=0.0
        i=0
        for camerakey in tmpRatio:
            i+=1
            if i==1:
                ratio=tmpRatio[camerakey]
            else:
                ratio=max(ratio,tmpRatio[camerakey]) + min(ratio,tmpRatio[camerakey])*(1-threshold)#计算被销售跟随顾客的比率

        return ratio

    def getTrackMat(self,track1,track2):
        '''
        把顾客的轨迹转换成轨迹矩阵
        :param track1: (list)轨迹1
        :param track2:（list）轨迹2
        :return:[[]]如[[0, 0], [1, 1], [2, 4], [2, 1], [2, 0],[3,3]]
        '''
        t1 = map(lambda x: [(x[2] + x[4]) / 2, (x[3] + x[5]) / 2], track1)

        t2 = map(lambda x: [(x[2] + x[4]) / 2, (x[3] + x[5]) / 2], track2)

        return t1,t2



